/** 
 * Kendo UI v2016.3.1118 (http://www.telerik.com/kendo-ui)                                                                                                                                              
 * Copyright 2016 Telerik AD. All rights reserved.                                                                                                                                                      
 *                                                                                                                                                                                                      
 * Kendo UI commercial licenses may be obtained at                                                                                                                                                      
 * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete                                                                                                                                  
 * If you do not own a commercial license, this file shall be governed by the trial license terms.                                                                                                      
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       
                                                                                                                                                                                                       

*/
(function (f, define) {
    define('kendo.mobile.listview', [
        'kendo.data',
        'kendo.userevents',
        'kendo.mobile.button'
    ], f);
}(function () {
    var __meta__ = {
        id: 'mobile.listview',
        name: 'ListView',
        category: 'mobile',
        description: 'The Kendo Mobile ListView widget is used to display flat or grouped list of items.',
        depends: [
            'data',
            'userevents',
            'mobile.button'
        ]
    };
    (function ($, undefined) {
        var kendo = window.kendo, Node = window.Node, mobile = kendo.mobile, ui = mobile.ui, outerHeight = kendo._outerHeight, DataSource = kendo.data.DataSource, Widget = ui.DataBoundWidget, ITEM_SELECTOR = '.km-list > li, > li:not(.km-group-container)', HIGHLIGHT_SELECTOR = '.km-listview-link, .km-listview-label', ICON_SELECTOR = '[' + kendo.attr('icon') + ']', proxy = $.proxy, attrValue = kendo.attrValue, GROUP_CLASS = 'km-group-title', ACTIVE_CLASS = 'km-state-active', GROUP_WRAPPER = '<div class="' + GROUP_CLASS + '"><div class="km-text"></div></div>', GROUP_TEMPLATE = kendo.template('<li><div class="' + GROUP_CLASS + '"><div class="km-text">#= this.headerTemplate(data) #</div></div><ul>#= kendo.render(this.template, data.items)#</ul></li>'), WRAPPER = '<div class="km-listview-wrapper" />', SEARCH_TEMPLATE = kendo.template('<form class="km-filter-form"><div class="km-filter-wrap"><input type="search" placeholder="#=placeholder#"/><a href="\\#" class="km-filter-reset" title="Clear"><span class="km-icon km-clear"></span><span class="km-text">Clear</span></a></div></form>'), NS = '.kendoMobileListView', STYLED = 'styled', DATABOUND = 'dataBound', DATABINDING = 'dataBinding', ITEM_CHANGE = 'itemChange', CLICK = 'click', CHANGE = 'change', PROGRESS = 'progress', FUNCTION = 'function', whitespaceRegExp = /^\s+$/, buttonRegExp = /button/;
        function whitespace() {
            return this.nodeType === Node.TEXT_NODE && this.nodeValue.match(whitespaceRegExp);
        }
        function addIcon(item, icon) {
            if (icon && !item[0].querySelector('.km-icon')) {
                item.prepend('<span class="km-icon km-' + icon + '"/>');
            }
        }
        function enhanceItem(item) {
            addIcon(item, attrValue(item, 'icon'));
            addIcon(item, attrValue(item.children(ICON_SELECTOR), 'icon'));
        }
        function enhanceLinkItem(item) {
            var parent = item.parent(), itemAndDetailButtons = item.add(parent.children(kendo.roleSelector('detailbutton'))), otherNodes = parent.contents().not(itemAndDetailButtons).not(whitespace);
            if (otherNodes.length) {
                return;
            }
            item.addClass('km-listview-link').attr(kendo.attr('role'), 'listview-link');
            addIcon(item, attrValue(parent, 'icon'));
            addIcon(item, attrValue(item, 'icon'));
        }
        function enhanceCheckBoxItem(label) {
            if (!label[0].querySelector('input[type=checkbox],input[type=radio]')) {
                return;
            }
            var item = label.parent();
            if (item.contents().not(label).not(function () {
                    return this.nodeType == 3;
                })[0]) {
                return;
            }
            label.addClass('km-listview-label');
            label.children('[type=checkbox],[type=radio]').addClass('km-widget km-icon km-check');
        }
        function putAt(element, top) {
            $(element).css('transform', 'translate3d(0px, ' + top + 'px, 0px)');
        }
        var HeaderFixer = kendo.Class.extend({
            init: function (listView) {
                var scroller = listView.scroller();
                if (!scroller) {
                    return;
                }
                this.options = listView.options;
                this.element = listView.element;
                this.scroller = listView.scroller();
                this._shouldFixHeaders();
                var headerFixer = this;
                var cacheHeaders = function () {
                    headerFixer._cacheHeaders();
                };
                listView.bind('resize', cacheHeaders);
                listView.bind(STYLED, cacheHeaders);
                listView.bind(DATABOUND, cacheHeaders);
                this._scrollHandler = function (e) {
                    headerFixer._fixHeader(e);
                };
                scroller.bind('scroll', this._scrollHandler);
            },
            destroy: function () {
                var that = this;
                if (that.scroller) {
                    that.scroller.unbind('scroll', that._scrollHandler);
                }
            },
            _fixHeader: function (e) {
                if (!this.fixedHeaders) {
                    return;
                }
                var i = 0, scroller = this.scroller, headers = this.headers, scrollTop = e.scrollTop, headerPair, offset, header;
                do {
                    headerPair = headers[i++];
                    if (!headerPair) {
                        header = $('<div />');
                        break;
                    }
                    offset = headerPair.offset;
                    header = headerPair.header;
                } while (offset + 1 > scrollTop);
                if (this.currentHeader != i) {
                    scroller.fixedContainer.html(header.clone());
                    this.currentHeader = i;
                }
            },
            _shouldFixHeaders: function () {
                this.fixedHeaders = this.options.type === 'group' && this.options.fixedHeaders;
            },
            _cacheHeaders: function () {
                this._shouldFixHeaders();
                if (!this.fixedHeaders) {
                    return;
                }
                var headers = [], offset = this.scroller.scrollTop;
                this.element.find('.' + GROUP_CLASS).each(function (_, header) {
                    header = $(header);
                    headers.unshift({
                        offset: header.position().top + offset,
                        header: header
                    });
                });
                this.headers = headers;
                this._fixHeader({ scrollTop: offset });
            }
        });
        var DEFAULT_PULL_PARAMETERS = function () {
            return { page: 1 };
        };
        var RefreshHandler = kendo.Class.extend({
            init: function (listView) {
                var handler = this, options = listView.options, scroller = listView.scroller(), pullParameters = options.pullParameters || DEFAULT_PULL_PARAMETERS;
                this.listView = listView;
                this.scroller = scroller;
                listView.bind('_dataSource', function (e) {
                    handler.setDataSource(e.dataSource);
                });
                scroller.setOptions({
                    pullToRefresh: true,
                    pull: function () {
                        if (!handler._pulled) {
                            handler._pulled = true;
                            handler.dataSource.read(pullParameters.call(listView, handler._first));
                        }
                    },
                    messages: {
                        pullTemplate: options.messages.pullTemplate,
                        releaseTemplate: options.messages.releaseTemplate,
                        refreshTemplate: options.messages.refreshTemplate
                    }
                });
            },
            setDataSource: function (dataSource) {
                var handler = this;
                this._first = dataSource.view()[0];
                this.dataSource = dataSource;
                dataSource.bind('change', function () {
                    handler._change();
                });
                dataSource.bind('error', function () {
                    handler._change();
                });
            },
            _change: function () {
                var scroller = this.scroller, dataSource = this.dataSource;
                if (this._pulled) {
                    scroller.pullHandled();
                }
                if (this._pulled || !this._first) {
                    var view = dataSource.view();
                    if (view[0]) {
                        this._first = view[0];
                    }
                }
                this._pulled = false;
            }
        });
        var VirtualList = kendo.Observable.extend({
            init: function (options) {
                var list = this;
                kendo.Observable.fn.init.call(list);
                list.buffer = options.buffer;
                list.height = options.height;
                list.item = options.item;
                list.items = [];
                list.footer = options.footer;
                list.buffer.bind('reset', function () {
                    list.refresh();
                });
            },
            refresh: function () {
                var buffer = this.buffer, items = this.items, endReached = false;
                while (items.length) {
                    items.pop().destroy();
                }
                this.offset = buffer.offset;
                var itemConstructor = this.item, prevItem, item;
                for (var idx = 0; idx < buffer.viewSize; idx++) {
                    if (idx === buffer.total()) {
                        endReached = true;
                        break;
                    }
                    item = itemConstructor(this.content(this.offset + items.length));
                    item.below(prevItem);
                    prevItem = item;
                    items.push(item);
                }
                this.itemCount = items.length;
                this.trigger('reset');
                this._resize();
                if (endReached) {
                    this.trigger('endReached');
                }
            },
            totalHeight: function () {
                if (!this.items[0]) {
                    return 0;
                }
                var list = this, items = list.items, top = items[0].top, bottom = items[items.length - 1].bottom, averageItemHeight = (bottom - top) / list.itemCount, remainingItemsCount = list.buffer.length - list.offset - list.itemCount;
                return (this.footer ? this.footer.height : 0) + bottom + remainingItemsCount * averageItemHeight;
            },
            batchUpdate: function (top) {
                var height = this.height(), items = this.items, item, initialOffset = this.offset;
                if (!items[0]) {
                    return;
                }
                if (this.lastDirection) {
                    while (items[items.length - 1].bottom > top + height * 2) {
                        if (this.offset === 0) {
                            break;
                        }
                        this.offset--;
                        item = items.pop();
                        item.update(this.content(this.offset));
                        item.above(items[0]);
                        items.unshift(item);
                    }
                } else {
                    while (items[0].top < top - height) {
                        var nextIndex = this.offset + this.itemCount;
                        if (nextIndex === this.buffer.total()) {
                            this.trigger('endReached');
                            break;
                        }
                        if (nextIndex === this.buffer.length) {
                            break;
                        }
                        item = items.shift();
                        item.update(this.content(this.offset + this.itemCount));
                        item.below(items[items.length - 1]);
                        items.push(item);
                        this.offset++;
                    }
                }
                if (initialOffset !== this.offset) {
                    this._resize();
                }
            },
            update: function (top) {
                var list = this, items = this.items, item, firstItem, lastItem, height = this.height(), itemCount = this.itemCount, padding = height / 2, up = (this.lastTop || 0) > top, topBorder = top - padding, bottomBorder = top + height + padding;
                if (!items[0]) {
                    return;
                }
                this.lastTop = top;
                this.lastDirection = up;
                if (up) {
                    if (items[0].top > topBorder && items[items.length - 1].bottom > bottomBorder + padding && this.offset > 0) {
                        this.offset--;
                        item = items.pop();
                        firstItem = items[0];
                        item.update(this.content(this.offset));
                        items.unshift(item);
                        item.above(firstItem);
                        list._resize();
                    }
                } else {
                    if (items[items.length - 1].bottom < bottomBorder && items[0].top < topBorder - padding) {
                        var nextIndex = this.offset + itemCount;
                        if (nextIndex === this.buffer.total()) {
                            this.trigger('endReached');
                        } else if (nextIndex !== this.buffer.length) {
                            item = items.shift();
                            lastItem = items[items.length - 1];
                            items.push(item);
                            item.update(this.content(this.offset + this.itemCount));
                            list.offset++;
                            item.below(lastItem);
                            list._resize();
                        }
                    }
                }
            },
            content: function (index) {
                return this.buffer.at(index);
            },
            destroy: function () {
                this.unbind();
            },
            _resize: function () {
                var items = this.items, top = 0, bottom = 0, firstItem = items[0], lastItem = items[items.length - 1];
                if (firstItem) {
                    top = firstItem.top;
                    bottom = lastItem.bottom;
                }
                this.trigger('resize', {
                    top: top,
                    bottom: bottom
                });
                if (this.footer) {
                    this.footer.below(lastItem);
                }
            }
        });
        kendo.mobile.ui.VirtualList = VirtualList;
        var VirtualListViewItem = kendo.Class.extend({
            init: function (listView, dataItem) {
                var element = listView.append([dataItem], true)[0], height = element.offsetHeight;
                $.extend(this, {
                    top: 0,
                    element: element,
                    listView: listView,
                    height: height,
                    bottom: height
                });
            },
            update: function (dataItem) {
                this.element = this.listView.setDataItem(this.element, dataItem);
            },
            above: function (item) {
                if (item) {
                    this.height = this.element.offsetHeight;
                    this.top = item.top - this.height;
                    this.bottom = item.top;
                    putAt(this.element, this.top);
                }
            },
            below: function (item) {
                if (item) {
                    this.height = this.element.offsetHeight;
                    this.top = item.bottom;
                    this.bottom = this.top + this.height;
                    putAt(this.element, this.top);
                }
            },
            destroy: function () {
                kendo.destroy(this.element);
                $(this.element).remove();
            }
        });
        var LOAD_ICON = '<div><span class="km-icon"></span><span class="km-loading-left"></span><span class="km-loading-right"></span></div>';
        var VirtualListViewLoadingIndicator = kendo.Class.extend({
            init: function (listView) {
                this.element = $('<li class="km-load-more km-scroller-refresh" style="display: none"></li>').appendTo(listView.element);
                this._loadIcon = $(LOAD_ICON).appendTo(this.element);
            },
            enable: function () {
                this.element.show();
                this.height = outerHeight(this.element, true);
            },
            disable: function () {
                this.element.hide();
                this.height = 0;
            },
            below: function (item) {
                if (item) {
                    this.top = item.bottom;
                    this.bottom = this.height + this.top;
                    putAt(this.element, this.top);
                }
            }
        });
        var VirtualListViewPressToLoadMore = VirtualListViewLoadingIndicator.extend({
            init: function (listView, buffer) {
                this._loadIcon = $(LOAD_ICON).hide();
                this._loadButton = $('<a class="km-load">' + listView.options.messages.loadMoreText + '</a>').hide();
                this.element = $('<li class="km-load-more" style="display: none"></li>').append(this._loadIcon).append(this._loadButton).appendTo(listView.element);
                var loadMore = this;
                this._loadButton.kendoMobileButton().data('kendoMobileButton').bind('click', function () {
                    loadMore._hideShowButton();
                    buffer.next();
                });
                buffer.bind('resize', function () {
                    loadMore._showLoadButton();
                });
                this.height = outerHeight(this.element, true);
                this.disable();
            },
            _hideShowButton: function () {
                this._loadButton.hide();
                this.element.addClass('km-scroller-refresh');
                this._loadIcon.css('display', 'block');
            },
            _showLoadButton: function () {
                this._loadButton.show();
                this.element.removeClass('km-scroller-refresh');
                this._loadIcon.hide();
            }
        });
        var VirtualListViewItemBinder = kendo.Class.extend({
            init: function (listView) {
                var binder = this;
                this.chromeHeight = outerHeight(listView.wrapper.children().not(listView.element));
                this.listView = listView;
                this.scroller = listView.scroller();
                this.options = listView.options;
                listView.bind('_dataSource', function (e) {
                    binder.setDataSource(e.dataSource, e.empty);
                });
                listView.bind('resize', function () {
                    if (!binder.list.items.length) {
                        return;
                    }
                    binder.scroller.reset();
                    binder.buffer.range(0);
                    binder.list.refresh();
                });
                this.scroller.makeVirtual();
                this._scroll = function (e) {
                    binder.list.update(e.scrollTop);
                };
                this.scroller.bind('scroll', this._scroll);
                this._scrollEnd = function (e) {
                    binder.list.batchUpdate(e.scrollTop);
                };
                this.scroller.bind('scrollEnd', this._scrollEnd);
            },
            destroy: function () {
                this.list.unbind();
                this.buffer.unbind();
                this.scroller.unbind('scroll', this._scroll);
                this.scroller.unbind('scrollEnd', this._scrollEnd);
            },
            setDataSource: function (dataSource, empty) {
                var binder = this, options = this.options, listView = this.listView, scroller = listView.scroller(), pressToLoadMore = options.loadMore, pageSize, buffer, footer;
                this.dataSource = dataSource;
                pageSize = dataSource.pageSize() || options.virtualViewSize;
                if (!pageSize && !empty) {
                    throw new Error('the DataSource does not have page size configured. Page Size setting is mandatory for the mobile listview virtual scrolling to work as expected.');
                }
                if (this.buffer) {
                    this.buffer.destroy();
                }
                buffer = new kendo.data.Buffer(dataSource, Math.floor(pageSize / 2), pressToLoadMore);
                if (pressToLoadMore) {
                    footer = new VirtualListViewPressToLoadMore(listView, buffer);
                } else {
                    footer = new VirtualListViewLoadingIndicator(listView);
                }
                if (this.list) {
                    this.list.destroy();
                }
                var list = new VirtualList({
                    buffer: buffer,
                    footer: footer,
                    item: function (dataItem) {
                        return new VirtualListViewItem(listView, dataItem);
                    },
                    height: function () {
                        return scroller.height();
                    }
                });
                list.bind('resize', function () {
                    binder.updateScrollerSize();
                    listView.updateSize();
                });
                list.bind('reset', function () {
                    binder.footer.enable();
                });
                list.bind('endReached', function () {
                    footer.disable();
                    binder.updateScrollerSize();
                });
                buffer.bind('expand', function () {
                    list.lastDirection = false;
                    list.batchUpdate(scroller.scrollTop);
                });
                $.extend(this, {
                    buffer: buffer,
                    scroller: scroller,
                    list: list,
                    footer: footer
                });
            },
            updateScrollerSize: function () {
                this.scroller.virtualSize(0, this.list.totalHeight() + this.chromeHeight);
            },
            refresh: function () {
                this.list.refresh();
            },
            reset: function () {
                this.buffer.range(0);
                this.list.refresh();
            }
        });
        var ListViewItemBinder = kendo.Class.extend({
            init: function (listView) {
                var binder = this;
                this.listView = listView;
                this.options = listView.options;
                var itemBinder = this;
                this._refreshHandler = function (e) {
                    itemBinder.refresh(e);
                };
                this._progressHandler = function () {
                    listView.showLoading();
                };
                listView.bind('_dataSource', function (e) {
                    binder.setDataSource(e.dataSource);
                });
            },
            destroy: function () {
                this._unbindDataSource();
            },
            reset: function () {
            },
            refresh: function (e) {
                var action = e && e.action, dataItems = e && e.items, listView = this.listView, dataSource = this.dataSource, prependOnRefresh = this.options.appendOnRefresh, view = dataSource.view(), groups = dataSource.group(), groupedMode = groups && groups[0], item;
                if (action === 'itemchange') {
                    if (!listView._hasBindingTarget()) {
                        item = listView.findByDataItem(dataItems)[0];
                        if (item) {
                            listView.setDataItem(item, dataItems[0]);
                        }
                    }
                    return;
                }
                var removedItems, addedItems, addedDataItems;
                var adding = action === 'add' && !groupedMode || prependOnRefresh && !listView._filter;
                var removing = action === 'remove' && !groupedMode;
                if (adding) {
                    removedItems = [];
                } else if (removing) {
                    removedItems = listView.findByDataItem(dataItems);
                }
                if (listView.trigger(DATABINDING, {
                        action: action || 'rebind',
                        items: dataItems,
                        removedItems: removedItems,
                        index: e && e.index
                    })) {
                    if (this._shouldShowLoading()) {
                        listView.hideLoading();
                    }
                    return;
                }
                if (action === 'add' && !groupedMode) {
                    var index = view.indexOf(dataItems[0]);
                    if (index > -1) {
                        addedItems = listView.insertAt(dataItems, index);
                        addedDataItems = dataItems;
                    }
                } else if (action === 'remove' && !groupedMode) {
                    addedItems = [];
                    listView.remove(dataItems);
                } else if (groupedMode) {
                    listView.replaceGrouped(view);
                } else if (prependOnRefresh && !listView._filter) {
                    addedItems = listView.prepend(view);
                    addedDataItems = view;
                } else {
                    listView.replace(view);
                }
                if (this._shouldShowLoading()) {
                    listView.hideLoading();
                }
                listView.trigger(DATABOUND, {
                    ns: ui,
                    addedItems: addedItems,
                    addedDataItems: addedDataItems
                });
            },
            setDataSource: function (dataSource) {
                if (this.dataSource) {
                    this._unbindDataSource();
                }
                this.dataSource = dataSource;
                dataSource.bind(CHANGE, this._refreshHandler);
                if (this._shouldShowLoading()) {
                    this.dataSource.bind(PROGRESS, this._progressHandler);
                }
            },
            _unbindDataSource: function () {
                this.dataSource.unbind(CHANGE, this._refreshHandler).unbind(PROGRESS, this._progressHandler);
            },
            _shouldShowLoading: function () {
                var options = this.options;
                return !options.pullToRefresh && !options.loadMore && !options.endlessScroll;
            }
        });
        var ListViewFilter = kendo.Class.extend({
            init: function (listView) {
                var filter = this, filterable = listView.options.filterable, events = 'change paste', that = this;
                this.listView = listView;
                this.options = filterable;
                listView.element.before(SEARCH_TEMPLATE({ placeholder: filterable.placeholder || 'Search...' }));
                if (filterable.autoFilter !== false) {
                    events += ' keyup';
                }
                this.element = listView.wrapper.find('.km-search-form');
                this.searchInput = listView.wrapper.find('input[type=search]').closest('form').on('submit' + NS, function (e) {
                    e.preventDefault();
                }).end().on('focus' + NS, function () {
                    filter._oldFilter = filter.searchInput.val();
                }).on(events.split(' ').join(NS + ' ') + NS, proxy(this._filterChange, this));
                this.clearButton = listView.wrapper.find('.km-filter-reset').on(CLICK, proxy(this, '_clearFilter')).hide();
                this._dataSourceChange = $.proxy(this._refreshInput, this);
                listView.bind('_dataSource', function (e) {
                    e.dataSource.bind('change', that._dataSourceChange);
                });
            },
            _refreshInput: function () {
                var appliedFilters = this.listView.dataSource.filter();
                var searchInput = this.listView._filter.searchInput;
                if (!appliedFilters || appliedFilters.filters[0].field !== this.listView.options.filterable.field) {
                    searchInput.val('');
                } else {
                    searchInput.val(appliedFilters.filters[0].value);
                }
            },
            _search: function (expr) {
                this._filter = true;
                this.clearButton[expr ? 'show' : 'hide']();
                this.listView.dataSource.filter(expr);
            },
            _filterChange: function (e) {
                var filter = this;
                if (e.type == 'paste' && this.options.autoFilter !== false) {
                    setTimeout(function () {
                        filter._applyFilter();
                    }, 1);
                } else {
                    this._applyFilter();
                }
            },
            _applyFilter: function () {
                var options = this.options, value = this.searchInput.val(), expr = value.length ? {
                        field: options.field,
                        operator: options.operator || 'startswith',
                        ignoreCase: options.ignoreCase,
                        value: value
                    } : null;
                if (value === this._oldFilter) {
                    return;
                }
                this._oldFilter = value;
                this._search(expr);
            },
            _clearFilter: function (e) {
                this.searchInput.val('');
                this._search(null);
                e.preventDefault();
            }
        });
        var ListView = Widget.extend({
            init: function (element, options) {
                var listView = this;
                Widget.fn.init.call(this, element, options);
                element = this.element;
                options = this.options;
                if (options.scrollTreshold) {
                    options.scrollThreshold = options.scrollTreshold;
                }
                element.on('down', HIGHLIGHT_SELECTOR, '_highlight').on('move up cancel', HIGHLIGHT_SELECTOR, '_dim');
                this._userEvents = new kendo.UserEvents(element, {
                    fastTap: true,
                    filter: ITEM_SELECTOR,
                    allowSelection: true,
                    tap: function (e) {
                        listView._click(e);
                    }
                });
                element.css('-ms-touch-action', 'auto');
                element.wrap(WRAPPER);
                this.wrapper = this.element.parent();
                this._headerFixer = new HeaderFixer(this);
                this._itemsCache = {};
                this._templates();
                this.virtual = options.endlessScroll || options.loadMore;
                this._style();
                if (this.options.$angular && (this.virtual || this.options.pullToRefresh)) {
                    setTimeout($.proxy(this, '_start'));
                } else {
                    this._start();
                }
            },
            _start: function () {
                var options = this.options;
                if (this.options.filterable) {
                    this._filter = new ListViewFilter(this);
                }
                if (this.virtual) {
                    this._itemBinder = new VirtualListViewItemBinder(this);
                } else {
                    this._itemBinder = new ListViewItemBinder(this);
                }
                if (this.options.pullToRefresh) {
                    this._pullToRefreshHandler = new RefreshHandler(this);
                }
                this.setDataSource(options.dataSource);
                this._enhanceItems(this.items());
                kendo.notify(this, ui);
            },
            events: [
                CLICK,
                DATABINDING,
                DATABOUND,
                ITEM_CHANGE
            ],
            options: {
                name: 'ListView',
                style: '',
                type: 'flat',
                autoBind: true,
                fixedHeaders: false,
                template: '#:data#',
                headerTemplate: '<span class="km-text">#:value#</span>',
                appendOnRefresh: false,
                loadMore: false,
                endlessScroll: false,
                scrollThreshold: 30,
                pullToRefresh: false,
                messages: {
                    loadMoreText: 'Press to load more',
                    pullTemplate: 'Pull to refresh',
                    releaseTemplate: 'Release to refresh',
                    refreshTemplate: 'Refreshing'
                },
                pullOffset: 140,
                filterable: false,
                virtualViewSize: null
            },
            refresh: function () {
                this._itemBinder.refresh();
            },
            reset: function () {
                this._itemBinder.reset();
            },
            setDataSource: function (dataSource) {
                var emptyDataSource = !dataSource;
                this.dataSource = DataSource.create(dataSource);
                this.trigger('_dataSource', {
                    dataSource: this.dataSource,
                    empty: emptyDataSource
                });
                if (this.options.autoBind && !emptyDataSource) {
                    this.items().remove();
                    this.dataSource.fetch();
                }
            },
            destroy: function () {
                Widget.fn.destroy.call(this);
                kendo.destroy(this.element);
                this._userEvents.destroy();
                if (this._itemBinder) {
                    this._itemBinder.destroy();
                }
                if (this._headerFixer) {
                    this._headerFixer.destroy();
                }
                this.element.unwrap();
                delete this.element;
                delete this.wrapper;
                delete this._userEvents;
            },
            items: function () {
                if (this.options.type === 'group') {
                    return this.element.find('.km-list').children();
                } else {
                    return this.element.children().not('.km-load-more');
                }
            },
            scroller: function () {
                if (!this._scrollerInstance) {
                    this._scrollerInstance = this.element.closest('.km-scroll-wrapper').data('kendoMobileScroller');
                }
                return this._scrollerInstance;
            },
            showLoading: function () {
                var view = this.view();
                if (view && view.loader) {
                    view.loader.show();
                }
            },
            hideLoading: function () {
                var view = this.view();
                if (view && view.loader) {
                    view.loader.hide();
                }
            },
            insertAt: function (dataItems, index, triggerChange) {
                var listView = this;
                return listView._renderItems(dataItems, function (items) {
                    if (index === 0) {
                        listView.element.prepend(items);
                    } else if (index === -1) {
                        listView.element.append(items);
                    } else {
                        listView.items().eq(index - 1).after(items);
                    }
                    if (triggerChange) {
                        for (var i = 0; i < items.length; i++) {
                            listView.trigger(ITEM_CHANGE, {
                                item: items.eq(i),
                                data: dataItems[i],
                                ns: ui
                            });
                        }
                    }
                });
            },
            append: function (dataItems, triggerChange) {
                return this.insertAt(dataItems, -1, triggerChange);
            },
            prepend: function (dataItems, triggerChange) {
                return this.insertAt(dataItems, 0, triggerChange);
            },
            replace: function (dataItems) {
                this.options.type = 'flat';
                this._angularItems('cleanup');
                kendo.destroy(this.element.children());
                this.element.empty();
                this._userEvents.cancel();
                this._style();
                return this.insertAt(dataItems, 0);
            },
            replaceGrouped: function (groups) {
                this.options.type = 'group';
                this._angularItems('cleanup');
                this.element.empty();
                var items = $(kendo.render(this.groupTemplate, groups));
                this._enhanceItems(items.children('ul').children('li'));
                this.element.append(items);
                mobile.init(items);
                this._style();
                this._angularItems('compile');
            },
            remove: function (dataItems) {
                var items = this.findByDataItem(dataItems);
                this.angular('cleanup', function () {
                    return { elements: items };
                });
                kendo.destroy(items);
                items.remove();
            },
            findByDataItem: function (dataItems) {
                var selectors = [];
                for (var idx = 0, length = dataItems.length; idx < length; idx++) {
                    selectors[idx] = '[data-' + kendo.ns + 'uid=' + dataItems[idx].uid + ']';
                }
                return this.element.find(selectors.join(','));
            },
            setDataItem: function (item, dataItem) {
                var listView = this, replaceItem = function (items) {
                        var newItem = $(items[0]);
                        kendo.destroy(item);
                        listView.angular('cleanup', function () {
                            return { elements: [$(item)] };
                        });
                        $(item).replaceWith(newItem);
                        listView.trigger(ITEM_CHANGE, {
                            item: newItem,
                            data: dataItem,
                            ns: ui
                        });
                    };
                return this._renderItems([dataItem], replaceItem)[0];
            },
            updateSize: function () {
                this._size = this.getSize();
            },
            _renderItems: function (dataItems, callback) {
                var items = $(kendo.render(this.template, dataItems));
                callback(items);
                this.angular('compile', function () {
                    return {
                        elements: items,
                        data: dataItems.map(function (data) {
                            return { dataItem: data };
                        })
                    };
                });
                mobile.init(items);
                this._enhanceItems(items);
                return items;
            },
            _dim: function (e) {
                this._toggle(e, false);
            },
            _highlight: function (e) {
                this._toggle(e, true);
            },
            _toggle: function (e, highlight) {
                if (e.which > 1) {
                    return;
                }
                var clicked = $(e.currentTarget), item = clicked.parent(), role = attrValue(clicked, 'role') || '', plainItem = !role.match(buttonRegExp), prevented = e.isDefaultPrevented();
                if (plainItem) {
                    item.toggleClass(ACTIVE_CLASS, highlight && !prevented);
                }
            },
            _templates: function () {
                var template = this.options.template, headerTemplate = this.options.headerTemplate, dataIDAttribute = ' data-uid="#=arguments[0].uid || ""#"', templateProxy = {}, groupTemplateProxy = {};
                if (typeof template === FUNCTION) {
                    templateProxy.template = template;
                    template = '#=this.template(data)#';
                }
                this.template = proxy(kendo.template('<li' + dataIDAttribute + '>' + template + '</li>'), templateProxy);
                groupTemplateProxy.template = this.template;
                if (typeof headerTemplate === FUNCTION) {
                    groupTemplateProxy._headerTemplate = headerTemplate;
                    headerTemplate = '#=this._headerTemplate(data)#';
                }
                groupTemplateProxy.headerTemplate = kendo.template(headerTemplate);
                this.groupTemplate = proxy(GROUP_TEMPLATE, groupTemplateProxy);
            },
            _click: function (e) {
                if (e.event.which > 1 || e.event.isDefaultPrevented()) {
                    return;
                }
                var dataItem, item = e.target, target = $(e.event.target), buttonElement = target.closest(kendo.roleSelector('button', 'detailbutton', 'backbutton')), button = kendo.widgetInstance(buttonElement, ui), id = item.attr(kendo.attr('uid'));
                if (id) {
                    dataItem = this.dataSource.getByUid(id);
                }
                if (this.trigger(CLICK, {
                        target: target,
                        item: item,
                        dataItem: dataItem,
                        button: button
                    })) {
                    e.preventDefault();
                }
            },
            _styleGroups: function () {
                var rootItems = this.element.children();
                rootItems.children('ul').addClass('km-list');
                rootItems.each(function () {
                    var li = $(this), groupHeader = li.contents().first();
                    li.addClass('km-group-container');
                    if (!groupHeader.is('ul') && !groupHeader.is('div.' + GROUP_CLASS)) {
                        groupHeader.wrap(GROUP_WRAPPER);
                    }
                });
            },
            _style: function () {
                var options = this.options, grouped = options.type === 'group', element = this.element, inset = options.style === 'inset';
                element.addClass('km-listview').toggleClass('km-list', !grouped).toggleClass('km-virtual-list', this.virtual).toggleClass('km-listinset', !grouped && inset).toggleClass('km-listgroup', grouped && !inset).toggleClass('km-listgroupinset', grouped && inset);
                if (!element.parents('.km-listview')[0]) {
                    element.closest('.km-content').toggleClass('km-insetcontent', inset);
                }
                if (grouped) {
                    this._styleGroups();
                }
                this.trigger(STYLED);
            },
            _enhanceItems: function (items) {
                items.each(function () {
                    var item = $(this), child, enhanced = false;
                    item.children().each(function () {
                        child = $(this);
                        if (child.is('a')) {
                            enhanceLinkItem(child);
                            enhanced = true;
                        } else if (child.is('label')) {
                            enhanceCheckBoxItem(child);
                            enhanced = true;
                        }
                    });
                    if (!enhanced) {
                        enhanceItem(item);
                    }
                });
            }
        });
        ui.plugin(ListView);
    }(window.kendo.jQuery));
    return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
    (a3 || a2)();
}));